package com.ctshk.rpc.scenic.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.ScenicTicketStatus;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.scenic.dto.ScenicChargeDTO;
import com.ctshk.rpc.scenic.dto.ScenicResourceTicketDTO;
import com.ctshk.rpc.scenic.dto.app.ScenicProductEsDTO;
import com.ctshk.rpc.scenic.entity.ScenicProductCostStrategySpecStock;
import com.ctshk.rpc.scenic.entity.ScenicProductCostStrategyVaildDate;
import com.ctshk.rpc.scenic.entity.ScenicProductTicket;
import com.ctshk.rpc.scenic.mapper.ScenicProductCostStrategySpecStockMapper;
import com.ctshk.rpc.scenic.mapper.ScenicProductCostStrategyVaildDateMapper;
import com.ctshk.rpc.scenic.mapper.ScenicProductMapper;
import com.ctshk.rpc.scenic.mapper.ScenicProductTicketMapper;
import com.ctshk.rpc.scenic.req.ScenicResourceDownBox;
import com.ctshk.rpc.scenic.req.ScenicResourceTicketReq;
import com.ctshk.rpc.scenic.req.ScenicResourceTicketUpdateReq;
import com.ctshk.rpc.scenic.req.app.ScenicProductEsReq;
import com.ctshk.rpc.scenic.service.IScenicResourceTicketService;
import com.ctshk.rpc.scenic.service.app.IScenicTicketEsSearchService;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * <p>
 * 门票产品 服务实现类
 * </p>
 *
 * @author wangcy
 * @since 2021-02-02
 */
@DubboService
public class ScenicResourceTicketServiceImpl extends ServiceImpl<ScenicProductTicketMapper, ScenicProductTicket> implements IScenicResourceTicketService {

    @Autowired
    private ScenicProductCostStrategySpecStockMapper scenicProductCostStrategySpecStockMapper;
    @Autowired
    private ScenicProductCostStrategyVaildDateMapper scenicProductCostStrategyVaildDateMapper;
    @Autowired
    private ScenicProductTicketMapper scenicProductTicketMapper;
    @Autowired
    private ScenicProductMapper scenicProductMapper;
    @Autowired
    IScenicTicketEsSearchService iScenicTicketEsSearchService;

    @Override
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public Result<Long> createTicket(Long productId) {
        QueryWrapper<ScenicProductCostStrategySpecStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ScenicProductCostStrategySpecStock::getProductId, productId);

        List<ScenicProductCostStrategySpecStock> scenicProductCostStrategySpecStocks = scenicProductCostStrategySpecStockMapper.selectList(queryWrapper);
        scenicProductCostStrategySpecStocks.forEach(scenicProductCostStrategySpecStock -> {
            QueryWrapper<ScenicProductTicket> ticketQueryWrapper = new QueryWrapper<>();
            ticketQueryWrapper.lambda().select(ScenicProductTicket::getStockNumber).like(ScenicProductTicket::getStockNumber, scenicProductCostStrategySpecStock.getStockNumber());

            List<ScenicProductTicket> scenicProductTickets = baseMapper.selectList(ticketQueryWrapper);
            int maxNum = 0;
            int i = 1;
            Integer totalStock = scenicProductCostStrategySpecStock.getTotalStock();
            if (CollectionUtils.isNotEmpty(scenicProductTickets)) {
                totalStock = totalStock - scenicProductTickets.size();
                Optional<Integer> max = scenicProductTickets.stream().map(ticket -> {
                    String numStr = ticket.getStockNumber().substring(ticket.getStockNumber().length() - 4);
                    return Integer.parseInt(numStr);
                }).max(Integer::compare);
                if (max.isPresent()) {
                    maxNum = max.get();
                }
            }
            List<ScenicProductTicket> scenicProductTicketList = new ArrayList<>();
            while (i <= totalStock) {
                ScenicProductTicket scenicProductTicket = EntityUtil.convertBean(scenicProductCostStrategySpecStock, ScenicProductTicket.class);
                scenicProductTicket.setId(SnowflakeIdWorker.nextId());
                scenicProductTicket.setStockId(scenicProductCostStrategySpecStock.getId());
                int newStockNum = maxNum + i;
                scenicProductTicket.setStockNumber(scenicProductCostStrategySpecStock.getStockNumber() + String.format("%04d", newStockNum));
                scenicProductTicket.setStatus(ScenicTicketStatus.UNSOLD.getCode());
                scenicProductTicket.setGmtCreate(LocalDateTime.now());
                scenicProductTicketList.add(scenicProductTicket);
                i++;
            }
            try {
                super.saveBatch(scenicProductTicketList);
            } catch (Exception ignored) {}
        });
        return Result.success(productId);
    }

    @Override
    public PageResponse<ScenicResourceTicketDTO> queryList(ScenicResourceTicketReq resourceTicketReq) {

        IPage<ScenicProductTicket> iPage = new Page<>(resourceTicketReq.getPageNo(), resourceTicketReq.getPageSize());

        QueryWrapper<ScenicProductTicket> queryWrapper = new QueryWrapper<>();

        queryWrapper.lambda().eq(ScenicProductTicket::getProductId, resourceTicketReq.getProductId());

        if (null != resourceTicketReq.getAttr1Id()) {
            queryWrapper.lambda().eq(ScenicProductTicket::getAttr1Id, resourceTicketReq.getAttr1Id());
        }
        if (null != resourceTicketReq.getAttr2Id()) {
            queryWrapper.lambda().eq(ScenicProductTicket::getAttr2Id, resourceTicketReq.getAttr2Id());
        }
        if (StringUtils.isNotEmpty(resourceTicketReq.getStockNumber())) {
            queryWrapper.lambda().like(ScenicProductTicket::getStockNumber, resourceTicketReq.getStockNumber());
        }
        if (StringUtils.isNotEmpty(resourceTicketReq.getSupplierTicketNumber())) {
            queryWrapper.lambda().like(ScenicProductTicket::getSupplierTicketNumber, resourceTicketReq.getSupplierTicketNumber());
        }
        if (StringUtils.isNotEmpty(resourceTicketReq.getDepartmentName())) {
            queryWrapper.lambda().like(ScenicProductTicket::getDepartmentName, resourceTicketReq.getDepartmentName());
        }
        if (null != resourceTicketReq.getStatus()) {
            queryWrapper.lambda().eq(ScenicProductTicket::getStatus, resourceTicketReq.getStatus());
        }
        if (StringUtils.isNotEmpty(resourceTicketReq.getAttr1Name())) {
            queryWrapper.lambda().eq(ScenicProductTicket::getAttr1Name, resourceTicketReq.getAttr1Name());
        }
        if (StringUtils.isNotEmpty(resourceTicketReq.getAttr2Name())) {
            queryWrapper.lambda().eq(ScenicProductTicket::getAttr2Name, resourceTicketReq.getAttr2Name());
        }
        queryWrapper.orderByDesc("gmt_modified");
        queryWrapper.orderByDesc("id");
        IPage<ScenicProductTicket> scenicProductTicketIPage = baseMapper.selectPage(iPage, queryWrapper);
        if (CollectionUtils.isNotEmpty(scenicProductTicketIPage.getRecords())) {
            List<ScenicResourceTicketDTO> scenicResourceTicketDTOS = EntityUtil.copyList(scenicProductTicketIPage.getRecords(), ScenicResourceTicketDTO.class);
            return new PageResponse<>(scenicResourceTicketDTOS, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }
        return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    @Override
    public Result<List<ScenicResourceDownBox>> downBox(Long productId) {
        QueryWrapper<ScenicProductCostStrategySpecStock> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ScenicProductCostStrategySpecStock::getProductId, productId);
        List<ScenicProductCostStrategySpecStock> scenicProductCostStrategySpecStocks = scenicProductCostStrategySpecStockMapper.selectList(queryWrapper);
        return Result.success(EntityUtil.copyList(scenicProductCostStrategySpecStocks, ScenicResourceDownBox.class));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Long> updateStatus(List<Long> ids, ScenicTicketStatus status) {
        List<ScenicProductTicket> list = baseMapper.selectBatchIds(ids);

        // 批量售卖
        if (ScenicTicketStatus.BACK.getCode().equals(status.getCode())) {
            list = list.stream()
                    .filter(item -> ScenicTicketStatus.BACK.getCode().equals(item.getStatus())).peek(item -> {
                        item.setSupplierTicketNumber(null);
                        item.setDepartmentId(null);
                        item.setDepartmentName(null);
                        item.setSalerId(null);
                        item.setSalerName(null);
                        item.setSaleNumber(null);
                        item.setStatus(ScenicTicketStatus.UNSOLD.getCode());
                    }).collect(Collectors.toList());
            super.updateBatchById(list);
        }

        // 批量退回
        if (ScenicTicketStatus.UNSOLD.getCode().equals(status.getCode())) {
            list = list.stream()
                    .filter(item -> ScenicTicketStatus.UNSOLD.getCode().equals(item.getStatus())).peek(item -> {
                        item.setSupplierTicketNumber(null);
                        item.setDepartmentId(null);
                        item.setDepartmentName(null);
                        item.setSalerId(null);
                        item.setSalerName(null);
                        item.setSaleNumber(null);
                        item.setStatus(ScenicTicketStatus.BACK.getCode());
                    }).collect(Collectors.toList());
            super.updateBatchById(list);

            list.stream().map(ScenicProductTicket::getStockId)
                    .distinct()
                    .forEach(stockId -> {
                        // ScenicProductTicket scenicProductTicket = new ScenicProductTicket();
                        // scenicProductTicket.setStockId(stockId);
                        QueryWrapper<ScenicProductTicket> queryWrapper = new QueryWrapper<>();
                        queryWrapper.lambda().eq(ScenicProductTicket::getStockId, stockId);
                        queryWrapper.lambda().eq(ScenicProductTicket::getStatus, ScenicTicketStatus.SOLD.getCode())
                                .or().eq(ScenicProductTicket::getStatus, ScenicTicketStatus.UNSOLD.getCode());
                        ScenicProductCostStrategySpecStock scenicProductCostStrategySpecStock = scenicProductCostStrategySpecStockMapper.selectById(stockId);
                        scenicProductCostStrategySpecStock.setTotalStock(baseMapper.selectCount(queryWrapper));
                        scenicProductCostStrategySpecStockMapper.updateById(scenicProductCostStrategySpecStock);
                    });
        }
        //刷新es缓存
            CompletableFuture.runAsync(() -> {
                List<ScenicProductEsDTO> reqList = scenicProductMapper.selectAllProductListByids(ids);
                ScenicProductEsReq req1 = new ScenicProductEsReq();
                for(ScenicProductEsDTO dto : reqList) {
                    BeanUtils.copyProperties(dto,req1);
                    iScenicTicketEsSearchService.cacheUpdate(req1);
                }
            });

        return Result.success(ids.get(0));
    }

    @Override
    public Result<ScenicResourceTicketDTO> queryDetail(ScenicResourceTicketReq resourceTicketReq) {
        ScenicProductTicket scenicProductTicket = super.getById(resourceTicketReq.getId());
        ScenicResourceTicketDTO scenicResourceTicketDTO = null;
        if(scenicProductTicket != null){
            scenicResourceTicketDTO = EntityUtil.convertBean(scenicProductTicket,ScenicResourceTicketDTO.class);
        }
        return Result.success(scenicResourceTicketDTO);
    }

    @Override
    public Result<Long> queryTickeId(ScenicResourceTicketReq resourceTicketReq) {
        //生成当前时间
        String time = DateUtil.fmt(LocalDateTime.now());
        ScenicProductCostStrategyVaildDate strategyVaildDate = scenicProductCostStrategyVaildDateMapper.queryDetail(time,resourceTicketReq.getProductId());
        Long id = 0L;
        if(strategyVaildDate != null){
            ScenicResourceTicketReq req = new ScenicResourceTicketReq();
            req.setProductId(strategyVaildDate.getProductId());
            req.setStrategyId(strategyVaildDate.getStrategyId());
            req.setAttr1Name(resourceTicketReq.getAttr1Name());
            req.setAttr2Name(resourceTicketReq.getAttr2Name());
            ScenicProductTicket scenicProductTicket = scenicProductTicketMapper.queruDetail(req);
            if(scenicProductTicket!= null){
                id = scenicProductTicket.getId();
            }
        }
        return Result.success(id);
    }

    @Override
    public Result<List<ScenicResourceTicketDTO>> queryListByStatus(ScenicResourceTicketReq resourceTicketReq) {
        QueryWrapper<ScenicProductTicket> queryWrapper = new QueryWrapper();
        queryWrapper.eq("strategy_id",resourceTicketReq.getStrategyId());
        queryWrapper.eq("product_id",resourceTicketReq.getProductId());
        queryWrapper.eq("attr1_name",resourceTicketReq.getAttr1Name());
        queryWrapper.eq("attr2_name",resourceTicketReq.getAttr2Name());
        queryWrapper.eq("status",1);
        List<ScenicProductTicket> scenicProductTicketList = scenicProductTicketMapper.selectList(queryWrapper);
        List<ScenicResourceTicketDTO> list = EntityUtil.copyList(scenicProductTicketList,ScenicResourceTicketDTO.class);
        return Result.success(list);
    }

    @Override
    public Result<Long> update(ScenicResourceTicketUpdateReq req) {
        ScenicProductTicket scenicProductTicket = scenicProductTicketMapper.selectById(req.getId());
        if(scenicProductTicket != null){
            scenicProductTicket.setDepartmentId(req.getDepartmentId());
            scenicProductTicket.setDepartmentName(req.getDepartmentName());
            scenicProductTicket.setSaleNumber(req.getSaleNumber());
            scenicProductTicket.setStatus(2);
            scenicProductTicket.setSalerId(req.getSalerId());
            scenicProductTicket.setSalerName(req.getSalerName());
            scenicProductTicket.setGmtModified(LocalDateTime.now());
            scenicProductTicket.setSoldTime(LocalDateTime.now());
            scenicProductTicketMapper.updateById(scenicProductTicket);
        }
        return null;
    }

    @Override
    public Result<List<ScenicResourceTicketDTO>> queryByStockId(Long strategyId, Integer number) {
        List<ScenicProductTicket> scenicProductTicketList = scenicProductTicketMapper.queryByStockId(strategyId,number);
        List<ScenicResourceTicketDTO> list = EntityUtil.copyList(scenicProductTicketList,ScenicResourceTicketDTO.class);
        return Result.success(list);
    }

    @Override
    public Result<ScenicChargeDTO> queryChargeByStockId(Long strategyId) {
        return Result.success(scenicProductTicketMapper.queryChargeByStockId(strategyId));
    }

    @Override
    public  Result  updateSupplierTicketNumberByid(Long id,String supplierTicketNumber){
        scenicProductTicketMapper.updateSupplierTicketNumberByid(id,supplierTicketNumber);
        return Result.success();
    }

    @Override
    public Result backTicket(String ticketIds) {
        return Result.success(scenicProductTicketMapper.backTicket(ticketIds));
    }
}
